﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Reflection;
using TSharp.Core.Util; 
using TSharp.Core.Util.TypeConvert;

namespace JoinCheer.Scheduler.Test
{
    /// <summary>
    /// UnitTest2 的摘要说明
    /// </summary>
    [TestClass]
    public class UnitTest2
    {

        public UnitTest2()
        {
            //
            //TODO: 在此处添加构造函数逻辑
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///获取或设置测试上下文，该上下文提供
        ///有关当前测试运行及其功能的信息。
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region 附加测试属性
        //
        // 编写测试时，还可使用以下附加属性:
        //
        // 在运行类中的第一个测试之前使用 ClassInitialize 运行代码
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // 在类中的所有测试都已运行之后使用 ClassCleanup 运行代码
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // 在运行每个测试之前，使用 TestInitialize 来运行代码
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // 在每个测试运行完之后，使用 TestCleanup 来运行代码
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion
        #region ETest enum

        public enum ETest : byte
        {
            a = 1,
            b = 2,
        }



        [TestMethod]
        public void TestEnum()
        {
            //
            // TODO: 在此	添加测试逻辑
            //
            //  Assert.IsTrue(Enum.IsDefined(typeof(ETest), 1), "1没有在ETest中有定义");
            byte a = 1;
            Assert.IsTrue((ETest)a == ETest.a);
        }
        #endregion

        [TestMethod]
        public void BuildType()
        {
            var t = typeof(Int32);
            var namespaceName = t.Namespace;
            var a = t.Assembly;

            var types = a.GetTypes().Where(x => x.IsVisible && !x.IsGenericType && (x.IsClass || x.IsValueType) && x.Namespace == namespaceName).OrderBy(x => x.Name);
            Console.WriteLine(" #region 类型常量");
            foreach (var st in types)
            {
                Console.WriteLine(string.Format("public readonly static Type {0} = typeof({0});", st.Name));
            }
            Console.WriteLine("#endregion //类型常量");
        }
        [TestMethod]
        public void BuildTypeCode()
        {
            var ls = typeof(TypeCode).GetFields();
            StringBuilder interfaceMember = new StringBuilder();
            StringBuilder Switch = new StringBuilder();
            foreach (var m in ls)
            {
                interfaceMember.AppendFormat("TEnum {0}({0} judgeObj,TArg arg);\r\n", m.Name);
                Switch.AppendFormat(@" case TypeCode.{0}:
                    return judicative.{0}(({0})judgeObj,arg);
", m.Name);
            }
            Console.WriteLine(interfaceMember);
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine(Switch);
        }
        [TestMethod]
        public void BuildDetectorVoid()
        {
            var ls = typeof(TypeCode).GetFields().Where(x => x.Name != "value__" && x.Name != "Empty" && x.Name != "Object" && x.Name != "DBNull");
            StringBuilder voides = new StringBuilder("#region 常用类型探测方法");
            StringBuilder classes = new StringBuilder("#region 常用类型探测器实现类");
            foreach (var m in ls)
            {
                BuildDetectorVoid(m.Name, voides, classes);
            }
            BuildDetectorVoid(typeof(Guid).Name, voides, classes);
            BuildDetectorVoid(typeof(TimeSpan).Name, voides, classes);
            BuildDetectorVoid(typeof(Enum).Name, voides, classes);

            classes.AppendLine(" #endregion //常用类型探测器实现类");
            voides.AppendLine("#endregion //常用类型探测方法");
            Console.WriteLine(voides);
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine(classes);
        }

        private void BuildDetectorVoid(string typeName, StringBuilder voides, StringBuilder classes)
        {
            string NullableSign = "?";
            string NullablePrefix = "Nullable";
            string BaseType = string.Format("NullableValueTypeDetector<{0}>", typeName);
            string voidf = @"
        public static {0}{1} To{2}{0}(this object detectorObj, {0} defaultValue)
        {{
            return Detect(detectorObj, new {2}{0}TypeDetectorImpl(), defaultValue);
        }}
        public static {0}{1} To{2}{0}(this object detectorObj)
        {{
            return To{2}{0}(detectorObj, default({0}));
        }}
";
            var classf = @"
        #region {0}探测器实现类
        public class {2}{0}TypeDetectorImpl : {3}
        {{
            public override {0}{1} {0}({0} detectorObj, {0}{1} arg)
            {{
                return arg;
            }}
        }}       
        #endregion
";
            voides.AppendFormat(voidf, typeName, NullableSign, NullablePrefix);
            classes.AppendFormat(classf, typeName, NullableSign, NullablePrefix, BaseType);
        }
        [TestMethod]
        public void BuildLateBind()
        {
            var t = typeof(TypeFactory);


            t.GetNestedTypes().Any(x =>
            {
                if (!x.IsAbstract)
                {

                    var s = string.Format("[assembly: LateBinding(typeof(TSharp.Core.Util.TypeFactory.{0}{1}))]", x.Name, x.IsGenericType ? "<" + new string(',', x.GetGenericArguments().Length - 1) + ">" : "");
                    Console.WriteLine(s);
                }

                return false;
            });

        }
        [TestMethod]
        public void TestGetSingleNumber()
        {
            Random r = new Random();
            for (int i = 0, n = 100; i < n; i++)
            {
                int result = GetSingleNumber(r.Next(12345678));
                Console.WriteLine(result);
            }
        }

        private int GetSingleNumber(int N)
        {
            if (N < 0)
                throw new ArgumentException();
            int result = 0;
            while (N > 0)
            {
                result += N % 10;
                N = N / 10;
            }
            if (result < 10)
                return result;
            return GetSingleNumber(result);
        }
    }
}
